package com.atguigu.tingshu.user.service.impl;
import java.math.BigDecimal;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.common.util.MongoUtil;
import com.atguigu.tingshu.model.user.UserListenProcess;
import com.atguigu.tingshu.user.service.UserListenProcessService;
import com.atguigu.tingshu.vo.album.TrackStatMqVo;
import com.atguigu.tingshu.vo.user.LastUserListenPlayVo;
import com.atguigu.tingshu.vo.user.UserListenProcessVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserListenProcessServiceImpl implements UserListenProcessService {

	/**
	 * 用户声音播放进度的数据，数据量较大的。如果把这些数据都保存到一个集合中，该集合的数据就比较多，当数据量较大的时候基于一个集合实现数据的查询效率较低。
	 * 为了提高数据的查询消息，那么此时可以考虑对数据的进行分片存储【把声音的播放进度保存到不同的集合中】。
	 *
	 * 数据分片的规则：
	 * 1、针对每一个用户创建一个集合    UserListenProcess_1    UserListenProcess_2    UserListenProcess_3 .... UserListenProcess_xxx
	 * 2、可以固定集合的数量，然后根据用户的id进行分片   ----> 比如：存储声音播放进度的集合数量是100个，那么就根据用户的id进行取模运算，比如：userId % 100
	 *
	 * UserListenProcess_0 ，UserListenProcess_1 ， UserListenProcess_2 ...   UserListenProcess_99
	 *
	 */

	@Autowired
	private MongoTemplate mongoTemplate;

	@Autowired
	private RedisTemplate<String , String> redisTemplate ;

	@Autowired
	private KafkaService kafkaService ;

	@Override
	public void updateListenProcess(UserListenProcessVo userListenProcessVo) {

		// 获取当前登录的用户id
		Long userId = AuthContextHolder.getUserId();

		// 拼接集合名称
		String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId);

		// 根据用户的id和声音的id从mongodb对应的集合中查询声音的播放进度数据
		Query query = Query.query(Criteria.where("userId").is(userId).and("trackId").is(userListenProcessVo.getTrackId()));
		UserListenProcess listenProcess = mongoTemplate.findOne(query, UserListenProcess.class, collectionName);

		// 如果可以查询到数据执行更新操作
		if(listenProcess != null) {
			listenProcess.setBreakSecond(userListenProcessVo.getBreakSecond());
			listenProcess.setUpdateTime(new Date());
			mongoTemplate.save(listenProcess , collectionName) ;
		}else {		// 如果查询不到数据执行新增操作
			listenProcess = new UserListenProcess() ;
			listenProcess.setUserId(userId);
			listenProcess.setAlbumId(userListenProcessVo.getAlbumId());
			listenProcess.setTrackId(userListenProcessVo.getTrackId());
			listenProcess.setBreakSecond(userListenProcessVo.getBreakSecond());
			listenProcess.setCreateTime(new Date());
			listenProcess.setUpdateTime(new Date());
			mongoTemplate.save(listenProcess , collectionName) ;
		}

		// 查询Redis，判断当前的声音的播放量当前是否记录过
		String redisKey = "track:play:" + userId + ":" + userListenProcessVo.getTrackId() + ":" + DateUtil.format(new Date() , "yyyy-MM-dd");
		Boolean ifAbsent = redisTemplate.hasKey(redisKey);
		if(!ifAbsent) {

			// 向Kafka中发送消息
			TrackStatMqVo trackStatMqVo = new TrackStatMqVo() ;
			trackStatMqVo.setBusinessNo(UUID.randomUUID().toString().replace("-" , ""));
			trackStatMqVo.setAlbumId(userListenProcessVo.getAlbumId());
			trackStatMqVo.setTrackId(userListenProcessVo.getTrackId());
			trackStatMqVo.setStatType(SystemConstant.TRACK_STAT_PLAY);			// “0701”播放量
			trackStatMqVo.setCount(1);
			kafkaService.sendMsg(KafkaConstant.QUEUE_TRACK_STAT_UPDATE  , JSON.toJSONString(trackStatMqVo));

			// 在Redis记录播放量的记录标识
			redisTemplate.opsForValue().set(redisKey , JSON.toJSONString(trackStatMqVo)  , 1 , TimeUnit.DAYS);

		}

	}

	@Override
	public BigDecimal getTrackBreakSecond(Long trackId) {

		// 获取当前登录的用户id
		Long userId = AuthContextHolder.getUserId();

		// 拼接集合名称
		String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId);

		// 根据用户的id和声音的id从mongodb对应的集合中查询声音的播放进度数据
		Query query = Query.query(Criteria.where("userId").is(userId).and("trackId").is(trackId));
		UserListenProcess listenProcess = mongoTemplate.findOne(query, UserListenProcess.class, collectionName);
		if(listenProcess == null) {
			return new BigDecimal("0") ;
		}else {
			return listenProcess.getBreakSecond() ;
		}

	}

	@Override
	public LastUserListenPlayVo getLatelyTrack() {

		// 获取当前登录用户的id
		Long userId = AuthContextHolder.getUserId();

		// 拼接集合名称
		String collectionName = MongoUtil.getCollectionName(MongoUtil.MongoCollectionEnum.USER_LISTEN_PROCESS, userId);

		// 根据用户的id查询最后一次声音的播放信息
		Query query = Query.query(Criteria.where("userId").is(userId));
		query.with(Sort.by(Sort.Direction.DESC , "updateTime")) ;
		query.limit(1) ;
		UserListenProcess listenProcess = mongoTemplate.findOne(query, UserListenProcess.class, collectionName);

		LastUserListenPlayVo lastUserListenPlayVo = new LastUserListenPlayVo();
		if(listenProcess != null) {		// 用户之前播放过某一个声音
			lastUserListenPlayVo.setAlbumId(listenProcess.getAlbumId());
			lastUserListenPlayVo.setTrackId(listenProcess.getTrackId());
		}else {							// 用户之前没有播放过声音
			lastUserListenPlayVo.setAlbumId(383L);			// 给一个默认值
			lastUserListenPlayVo.setTrackId(20313L);
		}

		return lastUserListenPlayVo;
	}


}
